package com.aaa.yunMall.base;

import com.aaa.yunMall.util.Map2BeanUtil;
import com.aaa.yunMall.util.SpringContextUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.catalina.mapper.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.util.Sqls;

import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import static com.aaa.yunMall.staticproperties.OrderStatic.*;

/**
 * @author LQY
 * @date 2020-07-08 16:17
 */
public abstract class BaseService<T> {
    //全局变量
    private Class<T> cache = null;

    @Autowired
    private Mapper<T> mapper;

    private Mapper getMapper(){
        return mapper;
    }

    /**
     * 新增数据
     * @param t
     * @return
     */
    public Integer add(T t){
        return mapper.insert(t);
    }

    /**
     * 根据主键进行删除
     * @param t
     * @return
     */
    public Integer delete(T t){
        return mapper.deleteByPrimaryKey(t);
    }

    /**
     * 根据主键进行批量删除
     * @param ids
     * @return
     */
    public Integer deleteByIds(List<Integer> ids){
        Example example = Example.builder(getTypeArgument()).where(Sqls.custom().andIn("id", ids)).build();
        return mapper.deleteByExample(example);
    }

    /**
     * map转换实体类型
     * @param map
     * @return
     */
    public T newInstance(Map map){
        return (T)Map2BeanUtil.map2Bean(map,getTypeArgument());
    }

    /**
     * 获取子类泛型类型
     * @return
     */
    public Class<T> getTypeArgument(){
        if(null == cache){
            cache = (Class<T>)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        }
        return cache;
    }

    /**
     * 更新操作
     * @param t
     * @return
     */
    public Integer Update(T t){
        return mapper.updateByPrimaryKeySelective(t);
    }

    /**
     * 批量更新操作
     *  update username = ?  from user where id in (1,2,3,4,5,6,7)
     * @param t
     * @param ids
     * @return
     */
    public Integer batchUpdate(T t,Integer[] ids){
        Example example = Example.builder(getTypeArgument()).where(Sqls.custom().andIn("id", Arrays.asList(ids))).build();
        return mapper.updateByExample(t,example);
    }

    /**
     * 查询一条数据
     * @param t
     * @return
     */
    public T selectOne(T t){
        return mapper.selectOne(t);
    }

    /**
     * 查询一条数据
     *  可以排序
     *  fileds：不只是代表唯一键
     * @param where
     * @param orderByFiled
     * @param fileds
     * @return
     */
    public T selectOneByFiled(Sqls where,String orderByFiled,String... fileds){
        return (T) selectByFileds(null,null,where,orderByFiled,null,fileds).get(0);
    }

    /**
     * 通过条件查询一个列表
     * @param where
     * @param orderByFiled
     * @param fileds
     * @return
     */
    public List<T> selectListByFiled(Sqls where,String orderByFiled,String... fileds){
        return selectByFileds(null, null, where, orderByFiled, null, fileds);
    }

    /**
     * 实现条件查询的分页
     * @param pageNo
     * @param pageSize
     * @param where
     * @param orderFiled
     * @param fileds
     * @return
     */
    public PageInfo<T> selectListByPageAndFiled(Integer pageNo, Integer pageSize, Sqls where, String orderFiled, String... fileds){
        return new PageInfo<T>(selectByFileds(pageNo, pageSize, where, orderFiled, null, fileds));
    }

    /**
     * 查询集合，条件查询
     * @param t
     * @return
     */
    public List<T> selectList(T t){
        return mapper.select(t);
    }

    /**
     * 查询集合，分页查询
     * @param t
     * @param pageNo
     * @param pageSize
     * @return
     */
    public PageInfo<T> selectListByPage(T t,Integer pageNo, Integer pageSize){
        PageHelper.startPage(pageNo,pageSize);
        List<T> select = mapper.select(t);
        PageInfo<T> pageInfo = new PageInfo<T>(select);
        return pageInfo;
    }

    /**
     * 实现查询通用
     *  不但可以作用于分页，还可以作用于排序，还能作用于多条件查询
     *      orderByFiled:是所要排序的字段
     * @param pageNo
     * @param pageSize
     * @param where
     * @param orderByFiled
     * @param orderWord
     * @param fileds
     * @return
     */
    public List<T> selectByFileds(Integer pageNo,Integer pageSize,Sqls where, String orderByFiled, String orderWord, String... fileds){
        Example.Builder builder = null;
        if(null == fileds || fileds.length == 0){
            //查询所有数据
            builder = Example.builder(getTypeArgument());
        }else {
            //说明需要进行条件查询
            builder = Example.builder(getTypeArgument()).select(fileds);
        }
        if(null != where){
            //说明有用户自定义的where语句条件
            builder = builder.where(where);
        }
        if(null != orderByFiled){
            //说明需要对某个字段进行排序
            if(DESC.equals(orderWord.toUpperCase())){
                //说明需要倒序
                builder = builder.orderByDesc(orderByFiled);
            }else if(ASC.equals(orderWord.toUpperCase())){
                builder = builder.orderByAsc(orderByFiled);
            }else{
                builder = builder.orderByDesc(orderByFiled);
            }
        }
        Example example = builder.build();
        //实现分页
        if(pageNo != null & pageSize != null){
            PageHelper.startPage(pageNo,pageSize);
        }
        return getMapper().selectByExample(example);
    }

    /**
     * 获取spring容器/获取spring的上下文
     *      在项目开始运行的时候，会去加载spring配置，
     *      如果你们项目需要在项目启动的时候也加载自己的配置文件
     *      在spring的源码中有一个必须要看的方法(init())
     *      init()--->就是在项目启动的时候去加载spring的配置
     *       如果你的项目中也需要把某一些配置一开始就托管给spring
     *       需要获取到spring的上下文(ApplicationContext)
     * @return
     */
    public ApplicationContext getApplicationContext(){
        return SpringContextUtils.getApplicationContext();
    }

}
